import tkinter as tk
from tkinter import ttk,filedialog, messagebox
import threading
import time
import sys
import os
import re
import json
import requests
import ctypes
from pynput import mouse
import pyautogui
import pyperclip
from vocabulary_api import VocabularyAPI
from youdao_scraper import YoudaoDictScraper
from app_icon_manager import AppIconManager





class WordCaptureTool:
    def __init__(self):

        # 先设置AppID（必须在窗口创建前）
        if sys.platform == 'win32':
            ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID("MyCompany.MyApp.1.0")

        self.root = tk.Tk()
        self.root.title("英语单词查词工具")
        self.root.geometry("900x650")
        # 初始化图标管理器
        icon_manager = AppIconManager(self.root)
        self.root.configure(bg='#FEFEFE')

        """设置全局样式""" #ttk的设置在后面的set_global_style(self)中
        # 定义颜色变量（集中管理所有颜色）
        self.maintextframe_color = "#F8F8F3"  # 文本框背景色
        self.text_fg_color = "black"         # 文字颜色
        self.cursor_color = "black"          # 光标颜色
        self.border_color = "#e0e0e0"        # 边框颜色    
        self.crollbar_color =  "#FCF5F5"     #主页面滚动条背景色
        
        # 网络词典API配置
        self.api_url = "https://v2.xxapi.cn/api/englishwords"

        # 有道词典API配置
        self.youdao_api = YoudaoDictScraper()  # 添加这一行        

        # 本地词典API配置
        self.local_api = None
        self.initialize_local_api()     

        self.double_click_threshold = 0.25 #默认双击
        self.wait_times = [0.2, 0.4, 0.6]
        self.start_wait_time = 0.2  # 默认起始等待时间


        # 显示设置
        self.show_translations = tk.BooleanVar(value=True)
        self.show_synonyms = tk.BooleanVar(value=True)
        self.show_relwords = tk.BooleanVar(value=True)
        self.show_sentences = tk.BooleanVar(value=True)
        self.show_phrases = tk.BooleanVar(value=True)        

        # 默认词表设置
        self.default_wordlist = tk.StringVar()  # 存储默认词表名称
        self.load_default_wordlist_setting()    # 加载设置        
           
    
        
        # 监测状态
        self.monitoring = False
        self.listener = None
        self.last_click_time = 0
        self.click_count = 0
        self.last_click_button = None  # 新增：记录最后一次点击的按钮
        self.capturing = False



        # 长按监测相关变量（使用默认值）
        self.long_press_threshold = 1.0  # 长按时间阈值（秒）- 默认1秒
        self.long_press_position_threshold = 5  # 位置变化阈值（像素）
        self.long_press_start_time = 0
        self.long_press_start_position = (0, 0)
        self.long_press_active = False
        self.long_press_timer = None
        self.is_selecting = False  # 新增：标记是否正在选择（拖动中）
        self.selection_start_position = (0, 0)  # 新增：选择开始位置
        
        
        # 窗口置顶状态
        self.always_on_top = False
        
        # 弹窗引用
        self.popup_window = None

        # 用户词表管理器
        self.wordlist_manager = None        
        
        # 创建UI
        self.create_ui()
        self.set_global_style()
        
        # 启动主循环
        self.root.mainloop()
    
    def set_global_style(self):
        """设置全局样式"""
        # ttk样式配置...
        style = ttk.Style()
        
        # 基础框架样式
        style.configure('TFrame', background="#FEFEFE")
        
        # 按钮样式
        style.configure('TButton', 
                    font=("Microsoft YaHei", 10),
                    background='#FEFEFE',
                    foreground='black',
                    borderwidth=1,
                    relief='solid')
        style.map('TButton',
                background=[('active', '#f0f0f0')])
        
        # 特殊按钮样式
        style.configure('Accent.TButton',
                    background='#e0f0ff',
                    foreground='#0066cc')
        style.configure('Close.TButton',
                    font=("Microsoft YaHei", 10),
                    background='#FEFEFE',
                    foreground='red',
                    borderwidth=0)
        
        # 标签样式
        style.configure('TLabel', 
                    background='#FEFEFE', 
                    foreground='black',
                    font=("Microsoft YaHei", 10))
        style.configure('Title.TLabel', 
                    font=("Microsoft YaHei", 15, "bold"),
                    foreground='#1780c2')
        style.configure('Subtitle.TLabel',
                    font=("Microsoft YaHei", 10, "bold"),
                    foreground='#2c3e50')
        style.configure('Content.TLabel',
                    font=("Microsoft YaHei", 10),
                    foreground='#34495e')
        style.configure('Phonetic.TLabel',
                    font=("Microsoft YaHei", 10, "italic"),
                    foreground='#555555')
        
        # 文本框样式
        style.configure('TEntry',
                    font=("Microsoft YaHei", 10),
                    fieldbackground='#FEFEFE')
        
        # 复选框样式
        style.configure('TCheckbutton',
                    font=("Microsoft YaHei", 10),
                    background='#FEFEFE',
                    foreground='black')
        style.configure('#FEFEFE.TCheckbutton',
                    background='#FEFEFE',
                    foreground='black',
                    font=("Microsoft YaHei", 10))
        style.map('#FEFEFE.TCheckbutton',
                background=[('active', '#FEFEFE')])
        
        # 滚动条样式
        style.configure('TScrollbar', 
                    background=self.crollbar_color)
        
        # 添加弹窗禁用按钮样式（对应已添加单词)
        style.configure('Disabled.TButton',
                    background='#cccccc',
                    foreground='#666666')        
        
        # 选项卡样式
        style.configure('TNotebook', background='#FEFEFE')
        style.configure('TNotebook.Tab', 
                    background='#FEFEFE',
                    font=("Microsoft YaHei", 10),
                    padding=[10, 5])
        style.map('TNotebook.Tab',
                background=[('selected', '#FEFEFE')],
                foreground=[('selected', '#1780c2')])
        
        # 标签框架样式
        style.configure('#FEFEFE.TLabelframe', 
                    background='#FEFEFE',
                    bordercolor='#e0e0e0')
        style.configure('#FEFEFE.TLabelframe.Label',
                    background='#FEFEFE',
                    foreground='#1780c2',
                    font=("Microsoft YaHei", 10, "bold"))
        
        #查询结果框
        style.configure('#FEFEFE.ResultTLabelframe', 
                    background='#F7EFEF',
                    bordercolor='#e0e0e0')      

        self.maintextframe_color = "#F7F4F4" 


    def initialize_local_api(self):
        """初始化本地词典API"""
        try:
            # 获取基础路径（处理打包和开发模式）
            if getattr(sys, 'frozen', False):
                # 打包模式 - 使用相对路径
                base_path = os.path.dirname(sys.executable)
                vocab_path = os.path.join(base_path, 'raw', '合并词汇表_按单词排序.json')
            else:
                # 开发模式 - 直接定位到项目根目录
                # 当前文件在src目录中，项目根目录是src的上一级目录
                current_file_dir = os.path.dirname(os.path.abspath(__file__))  # 当前是src目录
                project_root = os.path.dirname(current_file_dir)  # 上一级就是项目根目录
                
                vocab_path = os.path.join(project_root, 'raw', '合并词汇表_按单词排序.json')
                print(f"🔍 开发模式路径信息:")
                print(f"   当前文件目录: {current_file_dir}")
                print(f"   项目根目录: {project_root}")
                print(f"   词汇表路径: {vocab_path}")
            
            # 检查文件是否存在
            if not os.path.exists(vocab_path):
                print(f"❌ 词汇表文件不存在: {vocab_path}")
                
                # 调试信息：显示目录结构
                print("🔍 目录结构调试信息:")
                if getattr(sys, 'frozen', False):
                    base_dir = os.path.dirname(sys.executable)
                else:
                    base_dir = project_root
                print(f"   基础目录: {base_dir}")
                if os.path.exists(base_dir):
                    print(f"   基础目录内容: {os.listdir(base_dir)}")
                    raw_dir = os.path.join(base_dir, "raw")
                    if os.path.exists(raw_dir):
                        print(f"   raw目录内容: {os.listdir(raw_dir)}")
                    else:
                        print(f"   raw目录不存在: {raw_dir}")
                
                self.local_api = None
                return
            
            print(f"✅ 找到词汇表文件: {vocab_path}")
            
            # 创建本地API实例
            self.local_api = VocabularyAPI(vocab_path)
            
            # 尝试初始化
            if self.local_api.initialize():
                print("✅ 本地词典API初始化成功")
            else:
                print("❌ 本地词典API初始化失败，将仅使用网络查询")
                self.local_api = None
                
        except Exception as e:
            print(f"❌ 本地词典API初始化异常: {e}")
            self.local_api = None
        
    def create_ui(self):
        """创建用户界面"""
        # 创建选项卡
        self.notebook = ttk.Notebook(self.root)
        self.notebook.pack(fill='both', expand=True, padx=10, pady=10)
        
        # 主界面
        self.main_frame = ttk.Frame(self.notebook)
        self.notebook.add(self.main_frame, text="查词")

        # 用户词表界面
        self.wordlist_frame = ttk.Frame(self.notebook)
        self.notebook.add(self.wordlist_frame, text="用户词表")        
        
        # 设置界面
        self.settings_frame = ttk.Frame(self.notebook)
        self.notebook.add(self.settings_frame, text="设置")
        
        # 填充主界面
        self.create_main_interface()

        # 填充用户词表界面
        self.create_wordlist_interface()        
        
        # 填充设置界面
        self.create_settings_interface()
    

    def create_wordlist_interface(self):
        """创建用户词表界面（使用独立的WordListManager类）"""
        self.wordlist_manager = WordListManager(self.wordlist_frame)
            
    def create_main_interface(self):
        """创建主界面"""
        # 控制按钮框架
        control_frame = ttk.Frame(self.main_frame)
        control_frame.pack(fill='x', padx=10, pady=10)
        
        # 监测开关按钮
        self.monitor_button = ttk.Button(
            control_frame,
            text="停止监测",
            command=self.toggle_monitoring
        )
        self.monitor_button.pack(side='left', padx=5)
        
        # 窗口置顶按钮
        self.topmost_button = ttk.Button(
            control_frame,
            text="窗口置顶",
            command=self.toggle_topmost
        )
        self.topmost_button.pack(side='left', padx=5)
        
        # 状态标签
        self.status_label = ttk.Label(
            control_frame,
            text="状态: 监测中"
        )
        self.status_label.pack(side='right', padx=5)
        
        # 结果显示区域
        self.result_frame = ttk.LabelFrame(
            self.main_frame,
            text="查询结果",
            padding=(10, 5, 10, 5),
            style='#FEFEFE.TLabelframe'  # 添加自定义样式
        )
        self.result_frame.pack(fill='both', expand=True, padx=10, pady=10)
        
        # 文本框和滚动条
        self.result_text = tk.Text(
            self.result_frame,
            height=15,
            width=40,
            font=("Microsoft YaHei", 10),
            wrap='word',
            bg=self.maintextframe_color,
            fg='black',
            insertbackground='black',
            padx=5,
            pady=5
        )
        self.result_text.pack(fill='both', expand=True, side='left')
        
        scrollbar = ttk.Scrollbar(
            self.result_frame,
            orient='vertical',
            command=self.result_text.yview
        )
        scrollbar.pack(side='right', fill='y')
        self.result_text.configure(yscrollcommand=scrollbar.set)
        
        # 文本标签样式
        self.result_text.tag_configure("title", 
                                     font=("Microsoft YaHei", 14, "bold"),
                                     foreground='#1780c2')
        self.result_text.tag_configure("subtitle", 
                                     font=("Microsoft YaHei", 12, "bold"),
                                     foreground='#2c3e50')
        self.result_text.tag_configure("phonetic", 
                                     font=("Microsoft YaHei", 10, "italic"),
                                     foreground='#555555')
        
        # 默认启动监测
        self.start_monitoring()
    
    def create_settings_interface(self):
        """创建设置界面"""
        # 显示选项框架
        options_frame = ttk.LabelFrame(
            self.settings_frame,
            text="单词详细卡显示选项",
            padding=(15, 10, 15, 10),
            style='#FEFEFE.TLabelframe'
        )
        options_frame.pack(fill='x', padx=10, pady=10)
        
        # 创建两列布局的Frame
        columns_frame = ttk.Frame(options_frame)
        columns_frame.pack(fill='x', expand=True)
        
        # 左列Frame
        left_column = ttk.Frame(columns_frame)
        left_column.pack(side='left', fill='both', expand=True, padx=5)
        
        # 右列Frame
        right_column = ttk.Frame(columns_frame)
        right_column.pack(side='left', fill='both', expand=True, padx=5)
        
        # 左列显示选项
        ttk.Checkbutton(
            left_column,
            text="显示单词释义",
            variable=self.show_translations
        ).pack(anchor='w', padx=5, pady=2)
        
        ttk.Checkbutton(
            left_column,
            text="显示近义词",
            variable=self.show_synonyms
        ).pack(anchor='w', padx=5, pady=2)
        
        ttk.Checkbutton(
            left_column,
            text="显示同根词",
            variable=self.show_relwords
        ).pack(anchor='w', padx=5, pady=2)
        
        # 右列显示选项
        ttk.Checkbutton(
            right_column,
            text="显示例句",
            variable=self.show_sentences
        ).pack(anchor='w', padx=5, pady=2)
        
        ttk.Checkbutton(
            right_column,
            text="显示短语",
            variable=self.show_phrases
        ).pack(anchor='w', padx=5, pady=2)

        # 默认词表设置框架
        wordlist_frame = ttk.LabelFrame(
            self.settings_frame,
            text="默认生词本设置",
            padding=(15, 10, 15, 10),
            style='#FEFEFE.TLabelframe'
        )
        wordlist_frame.pack(fill='x', padx=10, pady=10)
        
        # 创建一个水平排列的Frame
        label_combobox_frame = ttk.Frame(wordlist_frame)
        label_combobox_frame.pack(anchor='w', padx=5, pady=2, fill='x')

        # 标签放在左侧
        ttk.Label(
            label_combobox_frame,
            text="选择默认生词本:"
        ).pack(side='left', padx=(0, 5))

        # 获取可用的词表列表
        wordlist_names = self.get_wordlist_names()

        # 词表选择下拉框放在右侧
        self.wordlist_combobox = ttk.Combobox(
            label_combobox_frame,
            textvariable=self.default_wordlist,
            values=wordlist_names,
            state="readonly",
            width=30
        )
        self.wordlist_combobox.pack(side='left')

        # 绑定选择事件，选择后自动保存
        self.wordlist_combobox.bind('<<ComboboxSelected>>', self.on_default_wordlist_selected)
        
        # 绑定下拉框打开事件，刷新词表列表
        self.wordlist_combobox.bind('<Button-1>', self.on_combobox_click)
        self.wordlist_combobox.bind('<KeyPress-Down>', self.on_combobox_click)
        
        # 如果没有词表，显示提示
        if not wordlist_names:
            ttk.Label(
                wordlist_frame,
                text="可前往用户词表页面创建词表",
                foreground='orange'
            ).pack(anchor='w', padx=5, pady=2)
        
        # 双击设置框架
        threshold_frame = ttk.LabelFrame(
            self.settings_frame,
            text="取词参数设置",
            padding=(15, 10, 15, 10),
            style='#FEFEFE.TLabelframe'
        )
        threshold_frame.pack(fill='x', padx=10, pady=10)
        
        # 双击阈值设置
        threshold_input_frame = ttk.Frame(threshold_frame)
        threshold_input_frame.pack(anchor='w', padx=5, pady=2, fill='x')

        ttk.Label(
            threshold_input_frame,
            text="双击取词时间阈值(秒):"
        ).pack(side='left', padx=(0, 5))

        self.threshold_entry = ttk.Entry(
            threshold_input_frame,
            width=10
        )
        self.threshold_entry.insert(0, str(self.double_click_threshold))
        self.threshold_entry.pack(side='left')

        # 起始等待时间设置
        start_wait_frame = ttk.Frame(threshold_frame)
        start_wait_frame.pack(anchor='w', padx=5, pady=2, fill='x')
        
        ttk.Label(
            start_wait_frame,
            text="捕获等待时间(秒):"
        ).pack(side='left', padx=(0, 5))
        
        self.start_wait_entry = ttk.Entry(
            start_wait_frame,
            width=10
        )
        self.start_wait_entry.insert(0, str(self.start_wait_time))
        self.start_wait_entry.pack(side='left')

        # 统一的保存按钮
        save_all_btn = ttk.Button(
            self.settings_frame,
            text="保存所有设置",
            command=self.save_all_settings,
            style='Accent.TButton',
            width=20
        )
        save_all_btn.pack(side="bottom",pady=30)
        


        

    def save_all_settings(self):
        """保存所有设置（显示选项、双击设置、默认词表）"""
        try:
            # 验证并保存双击设置
            new_threshold = float(self.threshold_entry.get())
            if not (0.1 <= new_threshold <= 1.0):
                messagebox.showwarning("警告", "双击阈值必须在0.1到1.0秒之间")
                return
            
            new_start_wait = float(self.start_wait_entry.get())
            if not (0.1 <= new_start_wait <= 1.0):
                messagebox.showwarning("警告", "起始等待时间必须在0.1到1.0秒之间")
                return
            
            # 更新设置值
            self.double_click_threshold = new_threshold
            self.start_wait_time = new_start_wait
            self.wait_times = [
                self.start_wait_time,
                self.start_wait_time + 0.2,
                self.start_wait_time + 0.4
            ]
            
            # 保存到配置文件
            self.save_default_wordlist_setting()
            

            
            messagebox.showinfo("成功", "所有设置已保存")
            
        except ValueError:
            messagebox.showerror("错误", "请输入有效的数字")
        except Exception as e:
            messagebox.showerror("错误", f"保存失败: {str(e)}")




    def get_wordlist_names(self):
        """获取当前可用的词表名称列表"""
        wordlist_names = []
        if self.wordlist_manager:
            wordlist_names = list(self.wordlist_manager.wordlists.keys())
        return wordlist_names    
    
    def on_combobox_click(self, event=None):
        """当下拉框被点击时刷新词表列表"""
        # 刷新词表管理器数据（确保获取最新数据）
        if self.wordlist_manager:
            self.wordlist_manager.load_wordlists()
        
        # 获取最新的词表名称列表
        current_wordlists = self.get_wordlist_names()
        
        # 更新下拉框的值
        self.wordlist_combobox['values'] = current_wordlists
        
        # 检查当前选择的词表是否仍然存在
        current_selection = self.default_wordlist.get()
        if current_selection and current_selection not in current_wordlists:
            # 如果当前选择的词表不存在了，清空选择
            self.default_wordlist.set('')
            # 可选：显示提示信息
            print(f"警告：词表 '{current_selection}' 已不存在，已清空选择")
        
        # 如果没有词表，显示提示信息
        if not current_wordlists:
            messagebox.showwarning("警告", f"暂未创建词表，请前往用户词表页面创建词表")   

    def on_default_wordlist_selected(self, event=None):
        """当选择默认词表时更新状态显示（不再自动保存）"""
        selected_wordlist = self.default_wordlist.get()
        
        if selected_wordlist:
            # 验证选择的词表是否存在
            if self.wordlist_manager and selected_wordlist in self.wordlist_manager.wordlists:
                # 只更新状态显示，不自动保存
                if hasattr(self, 'settings_status_label'):
                    status_text = f"已选择词表: {selected_wordlist}（请点击'保存所有设置'生效）"
                    print(status_text)
            else:
                # 如果选择的词表不存在，清空选择并提示
                self.default_wordlist.set('')
                messagebox.showwarning("警告", f"选择的词表 '{selected_wordlist}' 不存在，请刷新词表列表")   


    def load_default_wordlist_setting(self):
        """加载默认词表设置、双击设置和显示选项"""
        try:
            if getattr(sys, 'frozen', False):
                base_path = os.path.dirname(sys.executable)
            else:
                base_path = os.path.dirname(os.path.abspath(__file__))
            
            config_file = os.path.join(base_path, 'user_config.json')
            
            if os.path.exists(config_file):
                with open(config_file, 'r', encoding='utf-8') as f:
                    config = json.load(f)
                    self.default_wordlist.set(config.get('default_wordlist', ''))
                    # 加载双击设置
                    self.double_click_threshold = config.get('double_click_threshold', 0.25)
                    self.start_wait_time = config.get('start_wait_time', 0.2)
                    # 计算等待时间序列
                    self.wait_times = [
                        self.start_wait_time,
                        self.start_wait_time + 0.2,
                        self.start_wait_time + 0.4
                    ]
                    
                    # 加载显示选项设置
                    self.show_translations.set(config.get('show_translations', True))
                    self.show_synonyms.set(config.get('show_synonyms', True))
                    self.show_relwords.set(config.get('show_relwords', True))
                    self.show_sentences.set(config.get('show_sentences', True))
                    self.show_phrases.set(config.get('show_phrases', True))
                    
                    print(f"设置加载成功: 默认词表={self.default_wordlist.get()}, 双击阈值={self.double_click_threshold}, 起始等待={self.start_wait_time}")
                    print(f"显示选项: 释义={self.show_translations.get()}, 近义词={self.show_synonyms.get()}, 同根词={self.show_relwords.get()}, 例句={self.show_sentences.get()}, 短语={self.show_phrases.get()}")
                    
            else:
                # 使用默认值
                self.double_click_threshold = 0.25
                self.start_wait_time = 0.2
                self.wait_times = [0.2, 0.4, 0.6]
                # 显示选项使用默认值True
                self.show_translations.set(True)
                self.show_synonyms.set(True)
                self.show_relwords.set(True)
                self.show_sentences.set(True)
                self.show_phrases.set(True)
                print("使用默认设置")
                
        except Exception as e:
            print(f"加载设置失败: {e}")
            # 使用默认值
            self.double_click_threshold = 0.25
            self.start_wait_time = 0.2
            self.wait_times = [0.2, 0.4, 0.6]
            # 显示选项使用默认值True
            self.show_translations.set(True)
            self.show_synonyms.set(True)
            self.show_relwords.set(True)
            self.show_sentences.set(True)
            self.show_phrases.set(True)




    def update_settings_display(self):
        """更新设置页面的输入框显示"""
        try:
            # 更新双击阈值输入框
            if hasattr(self, 'threshold_entry') and self.threshold_entry.winfo_exists():
                self.threshold_entry.delete(0, tk.END)
                self.threshold_entry.insert(0, str(self.double_click_threshold))
            
            # 更新起始等待时间输入框
            if hasattr(self, 'start_wait_entry') and self.start_wait_entry.winfo_exists():
                self.start_wait_entry.delete(0, tk.END)
                self.start_wait_entry.insert(0, str(self.start_wait_time))
                
            print("设置页面输入框已更新")
            
        except Exception as e:
            print(f"更新设置显示失败: {e}")


    def save_default_wordlist_setting(self):
        """保存默认词表设置、双击设置和显示选项"""
        try:
            if getattr(sys, 'frozen', False):
                base_path = os.path.dirname(sys.executable)
            else:
                base_path = os.path.dirname(os.path.abspath(__file__))
            
            config_file = os.path.join(base_path, 'user_config.json')
                
            config = {
                'default_wordlist': self.default_wordlist.get(),
                'double_click_threshold': self.double_click_threshold,
                'start_wait_time': self.start_wait_time,
                'show_translations': self.show_translations.get(),
                'show_synonyms': self.show_synonyms.get(),
                'show_relwords': self.show_relwords.get(),
                'show_sentences': self.show_sentences.get(),
                'show_phrases': self.show_phrases.get()
            }
            
            with open(config_file, 'w', encoding='utf-8') as f:
                json.dump(config, f, ensure_ascii=False, indent=2)
            
            print(f"设置已保存: 默认词表={self.default_wordlist.get()}, 双击阈值={self.double_click_threshold}, 起始等待={self.start_wait_time}")
            print(f"显示选项: 释义={self.show_translations.get()}, 近义词={self.show_synonyms.get()}, 同根词={self.show_relwords.get()}, 例句={self.show_sentences.get()}, 短语={self.show_phrases.get()}")
            
        except Exception as e:
            print(f"保存设置失败: {e}")
            # 不显示错误弹窗，避免干扰用户体验

    
    def toggle_monitoring(self):
        """切换监测状态"""
        if self.monitoring:
            self.stop_monitoring()
            self.monitor_button.config(text="开始监测")
            self.status_label.config(text="状态: 已停止")
        else:
            self.start_monitoring()
            self.monitor_button.config(text="停止监测")
            self.status_label.config(text="状态: 监测中（左/右键双击，左键拖动后静止1秒）")  # 修改这里
    
    def toggle_topmost(self):
        """切换窗口置顶状态"""
        self.always_on_top = not self.always_on_top
        self.root.attributes('-topmost', self.always_on_top)
        if self.always_on_top:
            self.topmost_button.config(text="取消置顶")
        else:
            self.topmost_button.config(text="窗口置顶")
    

    
    def save_api_settings(self):
        """保存API设置"""
        self.api_url = self.api_entry.get().strip()
        print(f"API URL已更新: {self.api_url}")
    
    def start_monitoring(self):
        """开始监测鼠标双击"""
        if not self.monitoring:
            self.monitoring = True
            self.listener_thread = threading.Thread(
                target=self.run_mouse_listener,
                daemon=True
            )
            self.listener_thread.start()
    
    def stop_monitoring(self):
        """停止监测鼠标双击和长按"""
        if self.monitoring:
            self.monitoring = False
            
            # 清理长按定时器和状态
            self.reset_long_press_state()
            
            # 停止鼠标监听器
            if self.listener:
                self.listener.stop()


    def run_mouse_listener(self):
        """运行鼠标监听器"""
        with mouse.Listener(on_click=self.on_click) as listener:
            self.listener = listener
            listener.join()
    
    def on_click(self, x, y, button, pressed):
        """鼠标点击事件处理 - 支持左键和右键双击，以及左键长按拖动后静止"""
        if not self.monitoring or self.capturing:
            return
        
        # 左键按下：开始选择阶段
        if button == mouse.Button.left and pressed:
            self.long_press_start_time = time.time()
            self.long_press_start_position = (x, y)
            self.selection_start_position = (x, y)  # 记录选择开始位置
            self.long_press_active = True
            self.is_selecting = True  # 进入选择阶段
            
            print(f"开始选择单词（位置: {x}, {y}）")
        
        # 左键释放：结束选择或捕获
        elif button == mouse.Button.left and not pressed:
            # 如果正在选择阶段，检查是否满足长按静止条件
            if self.is_selecting:
                current_time = time.time()
                selection_duration = current_time - self.long_press_start_time
                
                # 如果选择持续时间超过阈值，可能已经完成了选择
                if selection_duration > 0.3:  # 至少选择持续0.3秒才认为是有效选择
                    # 检查当前位置与选择开始位置的距离
                    current_x, current_y = pyautogui.position()
                    distance_from_start = ((current_x - self.selection_start_position[0]) ** 2 + 
                                        (current_y - self.selection_start_position[1]) ** 2) ** 0.5
                    
                    # 如果距离较大，说明进行了拖动选择
                    if distance_from_start > 10:
                        print(f"选择完成，拖动距离: {distance_from_start:.1f} 像素，等待静止...")
                        # 启动静止检测定时器
                        self.start_stillness_detection(current_x, current_y)
                    else:
                        # 没有拖动，直接结束
                        self.reset_long_press_state()
                else:
                    # 点击时间太短，不是有效选择
                    self.reset_long_press_state()
            else:
                self.reset_long_press_state()
        
        # 原有的双击检测逻辑（保持不变）
        if button in [mouse.Button.left, mouse.Button.right] and pressed:
            current_time = time.time()
            time_since_last_click = current_time - self.last_click_time
            
            # 检查是否是同一种按钮的双击
            if (time_since_last_click < self.double_click_threshold and 
                button == self.last_click_button):
                self.click_count += 1
                if self.click_count >= 1:
                    button_name = "左键" if button == mouse.Button.left else "右键"
                    print(f"检测到{button_name}双击，尝试捕获单词...")
                    self.capturing = True
                    
                    capture_thread = threading.Thread(
                        target=self.capture_word,
                        args=(x, y),
                        daemon=True
                    )
                    capture_thread.start()
                    
                    self.click_count = 0
            else:
                self.click_count = 0
            
            self.last_click_time = current_time
            self.last_click_button = button

    def start_stillness_detection(self, current_x, current_y):
        """开始静止检测"""
        if not self.long_press_active or self.capturing:
            return
        
        # 取消之前的定时器
        if self.long_press_timer:
            self.long_press_timer.cancel()
        
        # 启动静止检测定时器
        self.long_press_timer = threading.Timer(
            self.long_press_threshold, 
            self.check_stillness_and_capture, 
            args=(current_x, current_y)
        )
        self.long_press_timer.start()
        print(f"开始静止检测，需要保持静止 {self.long_press_threshold} 秒")


    def check_stillness_and_capture(self, check_x, check_y):
        """检查是否保持静止并触发捕获"""
        if not self.long_press_active or self.capturing:
            return
        
        try:
            # 获取当前鼠标位置
            current_x, current_y = pyautogui.position()
            
            # 计算位置变化
            distance = ((current_x - check_x) ** 2 + (current_y - check_y) ** 2) ** 0.5
            
            # 如果位置变化小于阈值，视为静止
            if distance < self.long_press_position_threshold:
                print(f"检测到鼠标静止 {self.long_press_threshold} 秒，开始捕获单词...")
                self.capturing = True
                self.is_selecting = False
                
                capture_thread = threading.Thread(
                    target=self.capture_word,
                    args=(current_x, current_y),
                    daemon=True
                )
                capture_thread.start()
            else:
                print(f"静止检测失败：鼠标移动了 {distance:.1f} 像素，重新开始检测...")
                # 重新开始静止检测
                self.start_stillness_detection(current_x, current_y)
                
        except Exception as e:
            print(f"静止检测异常: {e}")
            self.reset_long_press_state()   


    def reset_long_press_state(self):
        """重置长按相关状态"""
        self.long_press_active = False
        self.is_selecting = False
        if self.long_press_timer:
            self.long_press_timer.cancel()
            self.long_press_timer = None                 

    
    def capture_word(self, x, y):
        """捕获单词"""
        try:
            original_clipboard = pyperclip.paste()
        except:
            original_clipboard = ""
        
        word = None
        for wait_time in self.wait_times:
            time.sleep(wait_time)
            try:
                pyautogui.hotkey('ctrl', 'c')
                time.sleep(0.1)
                captured_text = pyperclip.paste().strip()
                
                if captured_text and captured_text != original_clipboard:
                    processed_word = self.process_and_validate_word(captured_text)
                    if processed_word:
                        word = processed_word
                        print(f"捕获到单词: {word}")
                        break
            except Exception as e:
                print(f"捕获单词失败: {e}")
        
        if word:
            query_thread = threading.Thread(
                target=self.query_word,
                args=(word, x, y),
                daemon=True
            )
            query_thread.start()
        else:
            print("未捕获到有效单词")
            self.capturing = False
    
    def process_and_validate_word(self, text):
        """处理和验证捕获的文本"""
        text = text.strip()
        
        if not text:
            return None
        
        if any('\u4e00' <= char <= '\u9fff' for char in text):
            return None
        
        if not all(char.isalpha() or char in ('-', ' ') for char in text):
            return None
        
        if ' ' in text:
            parts = text.split()
            if not all(part.isalpha() for part in parts):
                return None
            return None
        
        return text.lower()
    
    def query_word(self, word, x, y):
        """查询单词 - 三级查询：本地 → 有道 → v2.xxapi.cn"""
        local_result = None
        word_category = None
        
        # 第一步：尝试本地词典查询（原始单词）
        if self.local_api:
            try:
                local_result = self.local_api.query_word(word)
                if local_result['success'] and local_result['exists']:
                    print(f"✅ 本地查询成功: {word}")
                    word_category = local_result['data'].get('category', '未知')
                    word_data = self.format_local_data(local_result['data'])
                    
                    matching_wordlists = []
                    if self.wordlist_manager:
                        matching_wordlists = self.wordlist_manager.get_all_wordlists(word)
                    
                    self.root.after(0, self.display_word_result, word, word_data, matching_wordlists, word_category)
                    self.root.after(0, self.show_word_popup, word, word_data, x, y, matching_wordlists, word_category)
                    self.capturing = False
                    return
                    
            except Exception as e:
                print(f"本地查询异常: {e}")
        
        # 第二步：如果原始单词查询失败，尝试去除后缀后查询本地词典
        processed_words = self.process_word_with_suffixes(word)
        
        for processed_word, suffix_type in processed_words:
            print(f"尝试处理后的单词: {processed_word} (原后缀: {suffix_type})")
            
            if self.local_api:
                try:
                    local_result = self.local_api.query_word(processed_word)
                    if local_result['success'] and local_result['exists']:
                        print(f"✅ 处理后查询成功: {processed_word} -> {word}")
                        word_category = local_result['data'].get('category', '未知')
                        word_data = self.format_local_data(local_result['data'])
                        
                        # 在结果显示中注明这是处理后的结果
                        word_data['original_word'] = word
                        word_data['processed_word'] = processed_word
                        word_data['suffix_type'] = suffix_type
                        
                        matching_wordlists = []
                        if self.wordlist_manager:
                            matching_wordlists = self.wordlist_manager.get_all_wordlists(word)
                        
                        self.root.after(0, self.display_word_result, word, word_data, matching_wordlists, word_category)
                        self.root.after(0, self.show_word_popup, word, word_data, x, y, matching_wordlists, word_category)
                        self.capturing = False
                        return
                        
                except Exception as e:
                    print(f"处理后单词查询异常: {e}")
        
        # 第三步：所有本地查询都失败，尝试网络查询（有道API优先）
        self.query_word_from_network(word, x, y)


    def query_word_from_network(self, word, x, y):
        """网络查询单词 - 有道API优先，v2.xxapi.cn备用"""
        
        # 第一步：尝试有道API查询（原始单词）
        try:
            youdao_result = self.youdao_api.get_word_info(word)
            if youdao_result.get("code") == 200 and youdao_result.get("data"):
                print(f"✅ 有道API查询成功: {word}")
                word_data = youdao_result.get("data", {})
                matching_wordlists = []
                if self.wordlist_manager:
                    matching_wordlists = self.wordlist_manager.get_all_wordlists(word)
                
                self.root.after(0, self.display_word_result, word, word_data, matching_wordlists, None)
                self.root.after(0, self.show_word_popup, word, word_data, x, y, matching_wordlists, None)
                self.capturing = False
                return
        except Exception as e:
            print(f"有道API查询异常: {e}")
        
        # 第二步：有道API原始单词查询失败，尝试处理后的单词
        processed_words = self.process_word_with_suffixes(word)
        
        for processed_word, suffix_type in processed_words:
            try:
                youdao_result = self.youdao_api.get_word_info(processed_word)
                if youdao_result.get("code") == 200 and youdao_result.get("data"):
                    print(f"✅ 有道API处理后查询成功: {processed_word} -> {word}")
                    word_data = youdao_result.get("data", {})
                    # 标记为处理后结果
                    word_data['original_word'] = word
                    word_data['processed_word'] = processed_word
                    word_data['suffix_type'] = suffix_type
                    
                    matching_wordlists = []
                    if self.wordlist_manager:
                        matching_wordlists = self.wordlist_manager.get_all_wordlists(word)
                    
                    self.root.after(0, self.display_word_result, word, word_data, matching_wordlists, None)
                    self.root.after(0, self.show_word_popup, word, word_data, x, y, matching_wordlists, None)
                    self.capturing = False
                    return
            except Exception as e:
                print(f"有道API处理后查询异常: {e}")
                continue
        
        # 第三步：有道API查询失败，尝试v2.xxapi.cn（原始单词）
        try:
            api_url = f"{self.api_url}?word={word}"
            response = requests.get(api_url, timeout=10)
            
            if response.status_code == 200:
                data = response.json()
                if data.get("code") == 200:
                    word_data = data.get("data", {})
                    matching_wordlists = []
                    if self.wordlist_manager:
                        matching_wordlists = self.wordlist_manager.get_all_wordlists(word)
                    
                    self.root.after(0, self.display_word_result, word, word_data, matching_wordlists, None)
                    self.root.after(0, self.show_word_popup, word, word_data, x, y, matching_wordlists, None)
                    self.capturing = False
                    return
        except Exception as e:
            print(f"v2.xxapi.cn原始单词查询异常: {e}")
        
        # 第四步：v2.xxapi.cn原始单词查询失败，尝试处理后的单词
        for processed_word, suffix_type in processed_words:
            try:
                api_url = f"{self.api_url}?word={processed_word}"
                response = requests.get(api_url, timeout=10)
                
                if response.status_code == 200:
                    data = response.json()
                    if data.get("code") == 200:
                        word_data = data.get("data", {})
                        # 标记为处理后结果
                        word_data['original_word'] = word
                        word_data['processed_word'] = processed_word
                        word_data['suffix_type'] = suffix_type
                        
                        matching_wordlists = []
                        if self.wordlist_manager:
                            matching_wordlists = self.wordlist_manager.get_all_wordlists(word)
                        
                        self.root.after(0, self.display_word_result, word, word_data, matching_wordlists, None)
                        self.root.after(0, self.show_word_popup, word, word_data, x, y, matching_wordlists, None)
                        self.capturing = False
                        return
            except Exception as e:
                print(f"v2.xxapi.cn处理后查询异常: {e}")
                continue
        
        # 所有查询都失败
        self.root.after(0, self.show_query_failed_notification, word, x, y)
        self.capturing = False



    def process_word_with_suffixes(self, word):
        """
        处理单词后缀，返回可能的原形单词列表
        返回格式: [(processed_word, suffix_type), ...]
        """
        word = word.lower()
        results = []
        
        # 1. 名词复数: -s, -es
        if word.endswith('es'):
            # 以-es结尾的复数形式
            if len(word) > 2:
                # 以-s, -x, -z, -ch, -sh结尾的名词加-es
                if word[-3] in ['s', 'x', 'z'] or word.endswith('ch') or word.endswith('sh'):
                    results.append((word[:-2], '名词复数-es'))
                # 辅音字母+y结尾，变y为i加-es
                elif word.endswith('ies') and len(word) > 3:
                    results.append((word[:-3] + 'y', '名词复数-ies'))
        
        if word.endswith('s') and not word.endswith('ss'):
            # 一般名词复数-s
            if len(word) > 1:
                results.append((word[:-1], '名词复数-s'))
        
        # 2. 动词第三人称单数: -s, -es (类似名词复数规则)
        if word.endswith('es') and len(word) > 2:
            if word[-3] in ['s', 'x', 'z'] or word.endswith('ch') or word.endswith('sh'):
                results.append((word[:-2], '动词第三人称单数-es'))
            elif word.endswith('ies') and len(word) > 3:
                results.append((word[:-3] + 'y', '动词第三人称单数-ies'))
        
        if word.endswith('s') and len(word) > 1 and not word.endswith('ss'):
            results.append((word[:-1], '动词第三人称单数-s'))
        
        # 3. 动词进行时/动名词: -ing
        if word.endswith('ing'):
            if len(word) > 3:
                # 以不发音的e结尾，去e加ing
                if word.endswith('ing') and word[-4] == 'e':
                    results.append((word[:-3] + 'e', '动词进行时-ing'))
                # 重读闭音节，双写辅音字母加ing
                elif len(word) > 4 and word[-4] == word[-5] and word[-4] in 'bdgmnprt':
                    results.append((word[:-4] + word[-4], '动词进行时-ing'))
                else:
                    results.append((word[:-3], '动词进行时-ing'))
        
        # 4. 动词过去式/过去分词: -ed
        if word.endswith('ed'):
            if len(word) > 2:
                # 以不发音的e结尾，直接加d（如like → liked）
                if word.endswith('ed') and word[-3] == 'e':
                    results.append((word[:-1], '动词过去式-ed'))  # 只去掉d
                
                # 重读闭音节，双写辅音字母加ed
                elif len(word) > 3 and word[-3] == word[-4] and word[-3] in 'bdgmnprt':
                    results.append((word[:-3] + word[-3], '动词过去式-ed'))
                
                # 一般情况：直接去掉ed
                else:
                    results.append((word[:-2], '动词过去式-ed'))
        
        # 5. 形容词比较级: -er
        if word.endswith('er'):
            if len(word) > 2:
                # 以不发音的e结尾，直接加r
                if word.endswith('er') and word[-3] == 'e':
                    results.append((word[:-1], '形容词比较级-er'))  # 只去掉r
                # 重读闭音节，双写辅音字母加er
                elif len(word) > 3 and word[-3] == word[-4] and word[-3] in 'bdgmnprt':
                    results.append((word[:-3] + word[-3], '形容词比较级-er'))
                # 辅音字母+y结尾，变y为i加er
                elif word.endswith('ier') and len(word) > 3:
                    results.append((word[:-3] + 'y', '形容词比较级-ier'))
                else:
                    results.append((word[:-2], '形容词比较级-er'))
        
        # 6. 形容词最高级: -est
        if word.endswith('est'):
            if len(word) > 3:
                # 以不发音的e结尾，直接加st
                if word.endswith('est') and word[-4] == 'e':
                    results.append((word[:-2], '形容词最高级-est'))  # 只去掉st
                # 重读闭音节，双写辅音字母加est
                elif len(word) > 4 and word[-4] == word[-5] and word[-4] in 'bdgmnprt':
                    results.append((word[:-4] + word[-4], '形容词最高级-est'))
                # 辅音字母+y结尾，变y为i加est
                elif word.endswith('iest') and len(word) > 4:
                    results.append((word[:-4] + 'y', '形容词最高级-iest'))
                else:
                    results.append((word[:-3], '形容词最高级-est'))
        
        # 7. 新增：处理以e结尾的单词的各种后缀变化
        if word.endswith('e'):
            # 处理以e结尾的各种可能变化
            base_word = word[:-1]  # 去掉e
            
            # 检查是否是动词的各种形式（如liked → like）
            if len(word) > 3:
                # 检查是否是过去式（如liked → like）
                if word.endswith('ed') and word[-3] == 'e':
                    results.append((base_word, '动词过去式-ed（去e加ed）'))
                
                # 检查是否是进行时（如liking → like）
                if word.endswith('ing') and word[-4] == 'e':
                    results.append((base_word, '动词进行时-ing（去e加ing）'))
                
                # 检查是否是形容词比较级（如nicer → nice）
                if word.endswith('er') and word[-3] == 'e':
                    results.append((base_word, '形容词比较级-er（去e加er）'))
                
                # 检查是否是形容词最高级（如nicest → nice）
                if word.endswith('est') and word[-4] == 'e':
                    results.append((base_word, '形容词最高级-est（去e加est）'))
        
        # 8. 新增：简单的去d规则（针对piled → pile这种情况）
        if word.endswith('d') and len(word) > 2:
            # 检查是否可能是以e结尾的动词过去式（如pile + d → piled）
            base_word_without_d = word[:-1]
            if base_word_without_d.endswith('e'):
                results.append((base_word_without_d, '动词过去式-d（直接加d）'))
            else:
                results.append((word[:-1], '可能过去式-d'))
        
        # 去重并确保处理后的单词长度合理
        unique_results = []
        seen = set()
        for processed_word, suffix_type in results:
            if processed_word and len(processed_word) >= 2 and processed_word not in seen:
                unique_results.append((processed_word, suffix_type))
                seen.add(processed_word)
        
        return unique_results

    def show_query_failed_notification(self, word, x, y):
        """显示查询失败通知"""
        message = f"单词 '{word}' 查询失败\n已尝试去除常见后缀但仍未找到"
        self.show_word_notification(message, x, y)
        print(f"❌ 单词查询失败: {word}")




    def format_local_data(self, local_data):
        """将本地数据格式化为与网络API相同的格式"""
        # 获取原始释义文本（例如："n. 印刷业；印花布...\nvt. 印刷；打印..."）
        definition_text = local_data.get('definition', '')
        
        # 按换行符分割成不同词性的释义
        definition_lines = definition_text.split('\n') if definition_text else []
        
        # 解析每一行，提取词性（pos）和中文翻译（tran_cn）
        translations = []
        for line in definition_lines:
            if not line.strip():  # 跳过空行
                continue
            
            # 使用正则匹配词性（如 "n.", "vt.", "vi."）和后续翻译
            import re
            match = re.match(r'^([a-z]+\.)\s*(.*)', line.strip())
            if match:
                pos = match.group(1)  # 词性（如 "n."）
                tran_cn = match.group(2)  # 中文翻译（如 "印刷业；印花布..."）
                translations.append({
                    "pos": pos,
                    "tran_cn": tran_cn
                })
        
        return {
            "ukphone": local_data.get('uk_phone', ''),
            "usphone": local_data.get('us_phone', ''),
            "translations": translations,  # 包含多个词性的释义
            "synonyms": [],
            "relWords": [],
            "phrases": [],
            "sentences": []
        }         
    
    def display_word_result(self, word, word_data, matching_wordlists=None, word_category=None):
        """在主窗口显示单词查询结果（应用显示选项设置）"""
        self.result_text.delete(1.0, tk.END)


        # 检查是否是处理后单词
        is_processed = 'processed_word' in word_data and 'suffix_type' in word_data
        
        if is_processed:
            # 显示处理后单词的提示信息
            processed_word = word_data['processed_word']
            suffix_type = word_data['suffix_type']
            self.result_text.insert(tk.END, f"⚠️ 注意: 已查询单词原形\n", "subtitle")
            self.result_text.insert(tk.END, f"原单词: {word} → 原形: {processed_word}\n")
            self.result_text.insert(tk.END, f"后缀类型: {suffix_type}\n\n")        
        
        # 根据是否在词表中设置背景色
        if matching_wordlists:
            self.result_text.configure(bg="#E6F7FF")  # 浅蓝色背景
            # 显示词表信息
            self.result_text.insert(tk.END, f"★ 该单词存在于以下词表: {', '.join(matching_wordlists)}\n\n", "subtitle")
        else:
            self.result_text.configure(bg=self.maintextframe_color)  # 默认背景

        # 如果是本地查询且有分类信息，添加分类显示
        if word_category:
            self.result_text.insert(tk.END, f"📚📚 类别: {word_category}\n\n", "subtitle")
        
        # 添加单词标题
        self.result_text.insert(tk.END, f"单词: {word}\n", "title")
        
        # 添加音标
        uk_phone = word_data.get("ukphone", "")
        us_phone = word_data.get("usphone", "")
        if uk_phone or us_phone:
            self.result_text.insert(tk.END, f"英音: {uk_phone}  美音: {us_phone}\n\n", "phonetic")
        
        # 显示单词释义（根据设置）
        if self.show_translations.get():
            translations = word_data.get("translations", [])
            if translations:
                self.result_text.insert(tk.END, "释义:\n", "subtitle")
                for trans in translations:
                    pos = trans.get("pos", "")
                    tran_cn = trans.get("tran_cn", "")
                    self.result_text.insert(tk.END, f"  {pos} {tran_cn}\n")
                self.result_text.insert(tk.END, "\n")
        else:
            self.result_text.insert(tk.END, "释义: [已隐藏]\n\n", "subtitle")
        
        # 显示近义词（根据设置）
        if self.show_synonyms.get():
            synonyms = word_data.get("synonyms", [])
            if synonyms:
                self.result_text.insert(tk.END, "近义词:\n", "subtitle")
                for syn in synonyms:
                    pos = syn.get("pos", "")
                    tran = syn.get("tran", "")
                    hwds = syn.get("Hwds", [])
                    
                    words_list = [hwd.get("word", "") for hwd in hwds]
                    if words_list:
                        self.result_text.insert(tk.END, f"  {pos}. {', '.join(words_list)}")
                        if tran:
                            self.result_text.insert(tk.END, f" ({tran})")
                        self.result_text.insert(tk.END, "\n")
                self.result_text.insert(tk.END, "\n")
        else:
            if synonyms := word_data.get("synonyms", []):
                self.result_text.insert(tk.END, "近义词: [已隐藏]\n\n", "subtitle")
        
        # 显示同根词（根据设置）
        if self.show_relwords.get():
            relwords = word_data.get("relWords", [])
            if relwords:
                self.result_text.insert(tk.END, "同根词:\n", "subtitle")
                for rel in relwords:
                    pos = rel.get("Pos", "")
                    hwds = rel.get("Hwds", [])
                    
                    words_list = []
                    for hwd in hwds:
                        word_text = hwd.get("hwd", "")
                        tran = hwd.get("tran", "")
                        if word_text and tran:
                            words_list.append(f"{word_text} ({tran})")
                    
                    if words_list:
                        self.result_text.insert(tk.END, f"  {pos}: {', '.join(words_list)}\n")
                self.result_text.insert(tk.END, "\n")
        else:
            if relwords := word_data.get("relWords", []):
                self.result_text.insert(tk.END, "同根词: [已隐藏]\n\n", "subtitle")
        
        # 显示短语（根据设置）
        if self.show_phrases.get():
            phrases = word_data.get("phrases", [])
            if phrases:
                self.result_text.insert(tk.END, "短语:\n", "subtitle")
                for phrase in phrases:
                    p_content = phrase.get("p_content", "")
                    p_cn = phrase.get("p_cn", "")
                    if p_content and p_cn:
                        self.result_text.insert(tk.END, f"  {p_content} - {p_cn}\n")
                self.result_text.insert(tk.END, "\n")
        else:
            if phrases := word_data.get("phrases", []):
                self.result_text.insert(tk.END, "短语: [已隐藏]\n\n", "subtitle")
        
        # 显示例句（根据设置）
        if self.show_sentences.get():
            sentences = word_data.get("sentences", [])
            if sentences:
                self.result_text.insert(tk.END, "例句:\n", "subtitle")
                for sentence in sentences:
                    s_content = sentence.get("s_content", "")
                    s_cn = sentence.get("s_cn", "")
                    if s_content and s_cn:
                        self.result_text.insert(tk.END, f"  {s_content}\n")
                        self.result_text.insert(tk.END, f"  {s_cn}\n\n")
        else:
            if sentences := word_data.get("sentences", []):
                self.result_text.insert(tk.END, "例句: [已隐藏]\n\n", "subtitle")


    
    def show_word_popup(self, word, word_data, x, y, matching_wordlists=None,word_category=None):
        """显示单词弹窗"""
        if self.popup_window and self.popup_window.winfo_exists():
            self.popup_window.destroy()
        
        self.popup_window = tk.Toplevel(self.root)
        self.popup_window.overrideredirect(True)
        self.popup_window.attributes('-topmost', True)
        
        # 根据是否在词表中设置背景色
        if matching_wordlists:
            # 为不同词表分配不同颜色（可以根据需要扩展更多颜色）
            color_map = {
                0: "#E6F7FF",  # 浅蓝色
                1: "#FFF2E6",  # 浅橙色
                2: "#F0F7E6",  # 浅绿色
                3: "#F7E6F7",  # 浅紫色
                4: "#E6F7F7",  # 浅青色
            }
            
            # 使用第一个匹配词表的索引来选择颜色
            color_index = min(len(matching_wordlists) - 1, len(color_map) - 1)
            bg_color = color_map[color_index]
            self.popup_window.configure(bg=bg_color)
        else:
            self.popup_window.configure(bg="#F1EAEA")  # 默认边框颜色
        
        # 使用 Frame 作为内容容器
        border_frame = ttk.Frame(self.popup_window)
        border_frame.pack(fill='both', expand=True, padx=2, pady=2)
        
        # 内容容器（白色背景）
        container = ttk.Frame(
            border_frame, 
            padding=(15, 10, 15, 10),
            style='#FEFEFE.TLabelframe'
        )
        container.pack(fill='both', expand=True)
        
        # 标题栏
        title_bar = ttk.Frame(container)
        title_bar.pack(fill='x', pady=(0, 10))
            
        # 第一行：单词标题和关闭按钮
        title_row = ttk.Frame(title_bar)
        title_row.pack(fill='x')


        # 在标题栏添加处理后单词的提示
        is_processed = 'processed_word' in word_data and 'suffix_type' in word_data
        
        if is_processed:
            processed_word = word_data['processed_word']
            suffix_type = word_data['suffix_type']
            
            # 添加提示信息
            tip_row = ttk.Frame(title_bar)
            tip_row.pack(fill='x', pady=(2, 0))

            title_label = ttk.Label(
                title_row,
                text=f"{processed_word}",
                style='Title.TLabel'
            )
            title_label.pack(side='left', padx=5)            
            
            tip_label = ttk.Label(
                tip_row,
                text=f"⚠️ 已查询原形: {processed_word} ({suffix_type})",
                style='Phonetic.TLabel',
                foreground='#FF6B00'
            )
            tip_label.pack(side='left', padx=5)     
        else :  # 没有处理过的单词
            title_label = ttk.Label(
                title_row,
                text=f"{word}",
                style='Title.TLabel'
            )
            title_label.pack(side='left', padx=5)

        close_btn = ttk.Button(
            title_row,
            text="×",
            width=2,
            command=self.popup_window.destroy,
            style='Close.TButton'
        )
        close_btn.pack(side='right',padx=9)          

        if word_category:
            category_row = ttk.Frame(title_bar)
            category_row.pack(fill='x', pady=(2, 0))
            
            category_label = ttk.Label(
                title_row,
                text=f"📚: {word_category}",
                style='Phonetic.TLabel',
                foreground='#009688'  # 青色强调
            )
            category_label.pack(side='right', padx=5)            
        
 
        
        # 第二行：词表信息（如果有）
        if matching_wordlists:
            wordlist_row = ttk.Frame(title_bar)
            wordlist_row.pack(fill='x', pady=(5, 0))
            
            wordlist_label = ttk.Label(
                wordlist_row,
                text=f"★ 已存于词表: {', '.join(matching_wordlists)}",
                style='Phonetic.TLabel',
                foreground='#FF6B00'  # 橙色强调
            )
            wordlist_label.pack(side='left', padx=5)

        # # 新增：第三行显示词书分类信息（如果有）
        # if word_category:
        #     category_row = ttk.Frame(title_bar)
        #     category_row.pack(fill='x', pady=(2, 0))
            
        #     category_label = ttk.Label(
        #         category_row,
        #         text=f"📚: {word_category}",
        #         style='Phonetic.TLabel',
        #         foreground='#009688'  # 青色强调
        #     )
        #     category_label.pack(side='left', padx=5)            
        

        
        # 内容区域
        content_frame = ttk.Frame(container)
        content_frame.pack(fill='both', expand=True)
        
        # 添加音标
        uk_phone = word_data.get("ukphone", "")
        us_phone = word_data.get("usphone", "")
        if uk_phone or us_phone:
            ttk.Label(
                content_frame,
                text=f" 英音: {uk_phone}  美音: {us_phone}",
                style='Phonetic.TLabel',
                padding=(0, 0, 0, 10)
            ).pack(anchor='w')
        
        # 添加释义
        translations = word_data.get("translations", [])
        if translations:
            ttk.Label(
                content_frame,
                text="释义:",
                style='Subtitle.TLabel',
                padding=(0, 5, 0, 5)
            ).pack(anchor='w')
            
            for trans in translations:
                pos = trans.get("pos", "")
                tran_cn = trans.get("tran_cn", "")
                if pos and tran_cn:
                    ttk.Label(
                        content_frame,
                        text=f"{pos} {tran_cn}",
                        style='Content.TLabel',
                        wraplength=350,
                        justify='left',
                        padding=(10, 0, 0, 0)
                    ).pack(anchor='w')
        
        # # 添加"显示全部信息"按钮
        # show_all_btn = ttk.Button(
        #     container,
        #     text="显示全部信息",
        #     style='Accent.TButton',
        #     command=lambda: self.show_all_info(word, word_data, x, y)
        # )
        # show_all_btn.pack(pady=(10, 0))


        # 按钮框架 - 将两个按钮并排显示
        button_frame = ttk.Frame(container)
        button_frame.pack(pady=(10, 0), fill='x')

        # 根据单词状态动态设置按钮
        if self.is_word_in_default_list(word):
            # 单词已在词表中，显示禁用按钮
            add_to_wordlist_btn = ttk.Button(
                button_frame,
                text="已在生词本",
                style='Disabled.TButton',
                state="disabled"
            )
        else:
            # 单词不在词表中，显示可点击按钮
            add_to_wordlist_btn = ttk.Button(
                button_frame,
                text="添加至生词本",
                style='Accent.TButton',
                command=lambda: self.add_word_to_default_list(word, add_to_wordlist_btn)
            )
        add_to_wordlist_btn.pack(side='left', padx=(0, 5), expand=True, fill='x')

        # 显示全部信息按钮
        show_all_btn = ttk.Button(
            button_frame,
            text="显示全部信息",
            style='Accent.TButton',
            command=lambda: self.show_all_info(word, word_data, x, y)
        )
        show_all_btn.pack(side='left', padx=(5, 0), expand=True, fill='x')

        

        
        # 绑定拖动事件
        title_label.bind("<ButtonPress-1>", self.start_move_popup)
        title_label.bind("<B1-Motion>", self.move_popup)
        
        # 计算初始大小
        self.popup_window.update_idletasks()
        req_width = container.winfo_reqwidth() + 20
        req_height = container.winfo_reqheight() + 20
        self.popup_window.geometry(f"{req_width}x{req_height}")
        
        # 调整窗口位置
        self.adjust_window_position(self.popup_window, x, y)
        self.popup_window.attributes('-alpha', 1.0)
        
        # 点击外部关闭逻辑
        def on_click(event):
            if not (0 <= event.x_root - self.popup_window.winfo_rootx() <= self.popup_window.winfo_width() and
                    0 <= event.y_root - self.popup_window.winfo_rooty() <= self.popup_window.winfo_height()):
                self.popup_window.destroy()
        
        self.popup_window.bind("<Button-1>", on_click)
        container.bind("<Button-1>", lambda e: "break")
        content_frame.bind("<Button-1>", lambda e: "break")
        title_bar.bind("<Button-1>", lambda e: "break")
        
        # 强制获取焦点
        self.popup_window.focus_force()
        
        # 备用关闭逻辑
        def check_focus():
            if not self.popup_window.focus_displayof():
                self.popup_window.destroy()
            else:
                self.popup_window.after(100, check_focus)
        
        self.popup_window.after(100, check_focus)


    def add_word_to_default_list(self, word, button):
        """将单词添加到默认词表并更新按钮状态（按加入顺序排序）"""
        if not self.default_wordlist.get():
            messagebox.showwarning("警告", "请先在设置页面设置默认生词本")
            return
        
        if not self.wordlist_manager:
            messagebox.showwarning("警告", "词表管理器未初始化")
            return
        
        # 获取默认词表信息
        default_list_info = self.wordlist_manager.wordlists.get(self.default_wordlist.get())
        if not default_list_info:
            messagebox.showerror("错误", f"默认生词本 '{self.default_wordlist.get()}' 不存在")
            return
        
        try:
            # 读取现有词表数据
            with open(default_list_info['filepath'], 'r', encoding='utf-8') as f:
                wordlist_data = json.load(f)
            
            # 获取当前单词列表（保留原有顺序）
            words = wordlist_data.get('words', [])
            word_lower = word.lower()
            
            # 检查是否已存在（不区分大小写）
            existing_words_lower = [w.lower() for w in words]
            if word_lower not in existing_words_lower:
                # 如果不存在，添加到列表末尾
                words.append(word)  # 保留原始大小写
                wordlist_data['words'] = words  # 保持原有顺序，新单词在最后
                wordlist_data['update_time'] = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
                
                # 保存更新
                with open(default_list_info['filepath'], 'w', encoding='utf-8') as f:
                    json.dump(wordlist_data, f, ensure_ascii=False, indent=2)
                
                # 刷新词表管理器
                self.wordlist_manager.load_wordlists()
                
                # 更新按钮状态
                button.config(
                    text="已在生词本",
                    state="disabled",
                    style='Disabled.TButton'
                )
                # 移除按钮的点击事件
                button.config(command=lambda: None)
                print(f"已添加单词 '{word}' 到默认生词本 '{self.default_wordlist.get()}'")
            else:
                print(f"单词 '{word}' 已存在于生词本中")
                
        except Exception as e:
            messagebox.showerror("错误", f"添加单词失败: {str(e)}")

      


    def is_word_in_default_list(self, word):
        """检查单词是否在默认词表中"""
        if not self.default_wordlist.get() or not self.wordlist_manager:
            return False
        
        word = word.lower()
        default_list_info = self.wordlist_manager.wordlists.get(self.default_wordlist.get())
        
        if not default_list_info:
            return False
        
        return word in [w.lower() for w in default_list_info['words']]     


    
    def show_all_info(self, word, word_data, x=None, y=None):
        """显示全部信息 - 使用网络API查询完整信息（优先使用处理后的单词）"""
        # 先关闭当前弹窗
        if self.popup_window and self.popup_window.winfo_exists():
            self.popup_window.destroy()
        
        if x is None or y is None:
            x, y = pyautogui.position()
        
        # 确定要查询的单词：优先使用处理后的单词
        query_word = word
        is_processed = 'processed_word' in word_data and 'suffix_type' in word_data
        
        if is_processed:
            query_word = word_data['processed_word']
            print(f"⚠️ 显示详细信息：使用处理后的单词 '{query_word}' 查询（原单词: {word}）")
        else:
            print(f"显示详细信息：使用原始单词 '{query_word}' 查询")
        
        # 显示加载提示
        loading_window = tk.Toplevel(self.root)
        loading_window.overrideredirect(True)
        loading_window.attributes('-topmost', True)
        loading_window.configure(bg='#FEFEFE')
        loading_window.geometry("500x120")  # 稍微加大窗口尺寸以容纳更多信息
        
        # 居中显示
        screen_width = self.root.winfo_screenwidth()
        screen_height = self.root.winfo_screenheight()
        x_pos = (screen_width - 500) // 2
        y_pos = (screen_height - 120) // 2
        loading_window.geometry(f"500x120+{x_pos}+{y_pos}")
        
        # 显示查询信息（特别是处理后的单词）
        if is_processed:
            loading_text = f"正在查询单词原形: {query_word}\n（原单词: {word}, 后缀: {word_data['suffix_type']}）"
        else:
            loading_text = f"正在查询单词: {query_word}"
        
        tk.Label(
            loading_window,
            text=loading_text,
            font=("微软雅黑", 12),
            fg="blue",
            bg="#FEFEFE",
            justify='center'
        ).pack(expand=True, pady=20)
        
        # 在新线程中执行网络查询
        query_thread = threading.Thread(
            target=self.query_network_api_for_full_info,
            args=(query_word, word, is_processed, word_data, x, y, loading_window),
            daemon=True
        )
        query_thread.start()

    def query_network_api_for_full_info(self, query_word, original_word, is_processed, word_data, x, y, loading_window):
        """在网络线程中查询完整信息（使用新的优先级）"""
        try:
            # 先尝试有道API
            youdao_result = self.youdao_api.get_word_info(query_word)
            if youdao_result.get("code") == 200 and youdao_result.get("data"):
                full_word_data = youdao_result.get("data", {})
                # 如果是处理后的单词，在数据中标记原单词信息
                if is_processed:
                    full_word_data['original_word'] = original_word
                    full_word_data['processed_word'] = query_word
                    full_word_data['suffix_type'] = word_data['suffix_type']
                
                print(f"✅ 有道API查询成功，数据长度: {len(str(full_word_data))} 字符")
                self.root.after(0, lambda: self.show_full_info(query_word, full_word_data, x, y, loading_window))
                return
        except Exception as e:
            print(f"有道API查询失败: {e}")
        
        # 有道API失败，尝试v2.xxapi.cn
        try:
            api_url = f"{self.api_url}?word={query_word}"
            response = requests.get(api_url, timeout=10)
            
            if response.status_code == 200:
                data = response.json()
                if data.get("code") == 200:
                    full_word_data = data.get("data", {})
                    if is_processed:
                        full_word_data['original_word'] = original_word
                        full_word_data['processed_word'] = query_word
                        full_word_data['suffix_type'] = word_data['suffix_type']
                    
                    print(f"✅ v2.xxapi.cn查询成功，数据长度: {len(str(full_word_data))} 字符")
                    self.root.after(0, lambda: self.show_full_info(query_word, full_word_data, x, y, loading_window))
                    return
        except Exception as e:
            print(f"v2.xxapi.cn查询失败: {e}")
        
        # 查询失败也关闭加载窗口
        self.root.after(0, loading_window.destroy)
        # 显示错误提示
        self.root.after(0, lambda: messagebox.showerror("错误", f"无法获取单词 '{query_word}' 的详细信息"))

    def show_full_info(self, word, full_data, x, y, loading_window):
        """显示完整信息"""
        # 关闭加载窗口
        if loading_window and loading_window.winfo_exists():
            loading_window.destroy()
        
        # 新增：通知主窗口更新信息
        # 检查单词是否在用户词表中
        matching_wordlists = []
        if self.wordlist_manager:
            matching_wordlists = self.wordlist_manager.get_all_wordlists(word)
        
        # 更新主窗口显示
        self.root.after(0, self.display_word_result, word, full_data, matching_wordlists, None)
        
        # 原有弹窗创建代码
        self.popup_window = tk.Toplevel(self.root)
        self.popup_window.title(f"单词详情: {word}")
        self.popup_window.attributes('-topmost', True)
        self.popup_window.configure(bg='#FEFEFE', padx=15, pady=15)
        
        # 创建滚动区域
        canvas = tk.Canvas(self.popup_window, bg='#FEFEFE')
        scrollbar = ttk.Scrollbar(self.popup_window, orient="vertical", command=canvas.yview)
        scrollable_frame = ttk.Frame(canvas, padding=(15, 10, 15, 10))
        
        scrollable_frame.bind(
            "<Configure>",
            lambda e: canvas.configure(scrollregion=canvas.bbox("all"))
        )
        
        canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
        canvas.configure(yscrollcommand=scrollbar.set, bg='#FEFEFE')
        
        canvas.pack(side="left", fill="both", expand=True)
        scrollbar.pack(side="right", fill="y")
        
        # 添加鼠标滚轮支持
        def on_mousewheel(event):
            canvas.yview_scroll(int(-1*(event.delta/120)), "units")
        
        canvas.bind_all("<MouseWheel>", on_mousewheel)
        
        # 添加完整信息
        self.add_word_info_to_frame(word, full_data, scrollable_frame)
        
        # 调整窗口
        self.popup_window.update_idletasks()
        width = min(450, self.popup_window.winfo_screenwidth() - 100)
        height = min(650, self.popup_window.winfo_screenheight() - 100)
        self.popup_window.geometry(f"{width}x{height}")
        self.adjust_window_position(self.popup_window, x, y)
        
        def on_close():
            try:
                canvas.unbind_all("<MouseWheel>")
            except:
                pass
            self.popup_window.destroy()
        
        self.popup_window.protocol("WM_DELETE_WINDOW", on_close)
    
    def add_word_info_to_frame(self, word, word_data, frame):
        """将单词信息添加到指定框架（应用显示选项设置）"""
        # 添加单词标题
        ttk.Label(
            frame, 
            text=f"单词: {word}", 
            style='Title.TLabel'
        ).pack(anchor='w', pady=(0, 5))
        
        # 添加音标
        uk_phone = word_data.get("ukphone", "")
        us_phone = word_data.get("usphone", "")
        if uk_phone or us_phone:
            ttk.Label(
                frame,
                text=f"英音: {uk_phone}  美音: {us_phone}",
                style='Phonetic.TLabel'
            ).pack(anchor='w', pady=(0, 10))
        
        # 添加释义（根据设置）
        if self.show_translations.get():
            translations = word_data.get("translations", [])
            if translations:
                ttk.Label(
                    frame,
                    text="释义:",
                    style='Subtitle.TLabel'
                ).pack(anchor='w')
                
                for trans in translations:
                    pos = trans.get("pos", "")
                    tran_cn = trans.get("tran_cn", "")
                    if pos and tran_cn:
                        ttk.Label(
                            frame,
                            text=f"  {pos}. {tran_cn}",
                            style='Content.TLabel',
                            wraplength=350,
                            justify='left'
                        ).pack(anchor='w')
        else:
            if translations := word_data.get("translations", []):
                ttk.Label(
                    frame,
                    text="释义: [已隐藏]",
                    style='Subtitle.TLabel'
                ).pack(anchor='w')
        
        # 添加近义词（根据设置）
        if self.show_synonyms.get():
            synonyms = word_data.get("synonyms", [])
            if synonyms:
                ttk.Label(
                    frame,
                    text="近义词:",
                    style='Subtitle.TLabel'
                ).pack(anchor='w', pady=(10, 0))
                
                for syn in synonyms:
                    pos = syn.get("pos", "")
                    tran = syn.get("tran", "")
                    hwds = syn.get("Hwds", [])
                    
                    words_list = [hwd.get("word", "") for hwd in hwds]
                    if words_list:
                        syn_text = f"  {pos}. {', '.join(words_list)}"
                        if tran:
                            syn_text += f" ({tran})"
                        
                        ttk.Label(
                            frame,
                            text=syn_text,
                            style='Content.TLabel',
                            wraplength=350,
                            justify='left'
                        ).pack(anchor='w')
        else:
            if synonyms := word_data.get("synonyms", []):
                ttk.Label(
                    frame,
                    text="近义词: [已隐藏]",
                    style='Subtitle.TLabel'
                ).pack(anchor='w', pady=(10, 0))
        
        # 添加同根词（根据设置）
        if self.show_relwords.get():
            relwords = word_data.get("relWords", [])
            if relwords:
                ttk.Label(
                    frame,
                    text="同根词:",
                    style='Subtitle.TLabel'
                ).pack(anchor='w', pady=(10, 0))
                
                for rel in relwords:
                    pos = rel.get("Pos", "")
                    hwds = rel.get("Hwds", [])
                    
                    words_list = []
                    for hwd in hwds:
                        word_text = hwd.get("hwd", "")
                        tran = hwd.get("tran", "")
                        if word_text and tran:
                            words_list.append(f"{word_text} ({tran})")
                    
                    if words_list:
                        ttk.Label(
                            frame,
                            text=f"  {pos}: {', '.join(words_list)}",
                            style='Content.TLabel',
                            wraplength=350,
                            justify='left'
                        ).pack(anchor='w')
        else:
            if relwords := word_data.get("relWords", []):
                ttk.Label(
                    frame,
                    text="同根词: [已隐藏]",
                    style='Subtitle.TLabel'
                ).pack(anchor='w', pady=(10, 0))
        
        # 添加短语（根据设置）
        if self.show_phrases.get():
            phrases = word_data.get("phrases", [])
            if phrases:
                ttk.Label(
                    frame,
                    text="短语:",
                    style='Subtitle.TLabel'
                ).pack(anchor='w', pady=(10, 0))
                
                for phrase in phrases:
                    p_content = phrase.get("p_content", "")
                    p_cn = phrase.get("p_cn", "")
                    if p_content and p_cn:
                        ttk.Label(
                            frame,
                            text=f"  {p_content} - {p_cn}",
                            style='Content.TLabel',
                            wraplength=350,
                            justify='left'
                        ).pack(anchor='w')
        else:
            if phrases := word_data.get("phrases", []):
                ttk.Label(
                    frame,
                    text="短语: [已隐藏]",
                    style='Subtitle.TLabel'
                ).pack(anchor='w', pady=(10, 0))
        
        # 添加例句（根据设置）
        if self.show_sentences.get():
            sentences = word_data.get("sentences", [])
            if sentences:
                ttk.Label(
                    frame,
                    text="例句:",
                    style='Subtitle.TLabel'
                ).pack(anchor='w', pady=(10, 0))
                
                for sentence in sentences:
                    s_content = sentence.get("s_content", "")
                    s_cn = sentence.get("s_cn", "")
                    if s_content and s_cn:
                        ttk.Label(
                            frame,
                            text=f"  {s_content}",
                            style='Content.TLabel',
                            wraplength=350,
                            justify='left'
                        ).pack(anchor='w')
                        
                        ttk.Label(
                            frame,
                            text=f"  {s_cn}",
                            style='Content.TLabel',
                            wraplength=350,
                            justify='left'
                        ).pack(anchor='w', pady=(0, 10))
        else:
            if sentences := word_data.get("sentences", []):
                ttk.Label(
                    frame,
                    text="例句: [已隐藏]",
                    style='Subtitle.TLabel'
                ).pack(anchor='w', pady=(10, 0))
    
    def start_move_popup(self, event):
        """记录拖动开始位置"""
        self.popup_window._drag_start_x = event.x
        self.popup_window._drag_start_y = event.y
    
    def move_popup(self, event):
        """处理窗口拖动"""
        x = self.popup_window.winfo_x() + (event.x - self.popup_window._drag_start_x)
        y = self.popup_window.winfo_y() + (event.y - self.popup_window._drag_start_y)
        self.popup_window.geometry(f"+{x}+{y}")
    
    def adjust_window_position(self, window, x, y):
        """调整窗口位置防止超出屏幕"""
        window.update_idletasks()
        width = window.winfo_width()
        height = window.winfo_height()
        
        screen_width = window.winfo_screenwidth()
        screen_height = window.winfo_screenheight()
        
        new_x = x - width - 15 if x - width - 10 >= 0 else x
        new_y = y + 18
        
        if new_y + height + 10 > screen_height:
            new_y = y - height if y - height >= 0 else 0
        
        if new_x + width > screen_width:
            new_x = x - width if x - width >= 0 else 0
        
        new_x = max(20, min(new_x, screen_width - width - 20))
        new_y = max(20, min(new_y, screen_height - height - 20))
        
        window.geometry(f"+{new_x}+{new_y}")
    
    def show_word_notification(self, message, x, y):
        """显示单词通知"""
        try:
            notification = tk.Toplevel(self.root)
            notification.overrideredirect(True)
            notification.attributes('-topmost', True)
            notification.configure(bg='#FEFEFE')
            
            window_width = 450
            window_height = 80
            
            screen_width = self.root.winfo_screenwidth()
            screen_height = self.root.winfo_screenheight()
            
            if x + window_width > screen_width:
                x = screen_width - window_width - 10
            if y + window_height > screen_height:
                y = screen_height - window_height - 10
            
            notification.geometry(f"{window_width}x{window_height}+{x}+{y}")
            
            font_style = ("Microsoft YaHei", 12)
            label = tk.Label(
                notification, 
                text=message, 
                padx=10, 
                pady=10, 
                font=font_style,
                bg='#FEFEFE',
                fg='black'
            )
            label.pack()
            
            notification.after(1000, notification.destroy)
        except Exception as e:
            print(f"通知创建失败: {e}")










class WordListManager:
    def __init__(self, parent_frame):
        self.parent_frame = parent_frame
        self.wordlists = {}
        self.current_edit_mode = False
        
        # UI配置
        self.maintextframe_color = "#F8F8F3"
        self.text_fg_color = "black"
        
        # 初始化界面
        self.create_interface()
        self.load_wordlists()
    
    def create_interface(self):
        """创建用户词表界面整体布局"""
        # 主分割窗口（左右3:1比例）
        self.main_paned = tk.PanedWindow(
            self.parent_frame,
            orient=tk.HORIZONTAL,
            sashwidth=0,  # 设置为0隐藏分割条
            sashrelief='flat',  # 设置为flat无立体效果
            bg='#FEFEFE',
            showhandle=False  # 不显示手柄
        )
        self.main_paned.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 左侧区域（占3/4宽度）
        self.left_frame = ttk.Frame(self.main_paned)
        self.main_paned.add(self.left_frame, width=600, minsize=400)
        
        # 右侧区域（占1/4宽度）
        self.right_frame = ttk.Frame(self.main_paned)
        self.main_paned.add(self.right_frame, width=200, minsize=150)
        
        # 构建左侧内容
        self.create_wordlist_treeview()
        
        # 构建右侧内容
        self.create_content_display()
        
        # 构建底部按钮区域
        self.create_bottom_buttons()
        
        # 配置分割比例
        self.main_paned.paneconfig(self.left_frame, stretch="always")
        self.main_paned.paneconfig(self.right_frame, stretch="never")
    
    def create_wordlist_treeview(self):
        """创建词表列表Treeview"""
        list_frame = ttk.LabelFrame(
            self.left_frame,
            text="词表列表",
            padding=(10, 5, 10, 5),
            style='#FEFEFE.TLabelframe'
        )
        list_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # Treeview组件
        self.wordlist_tree = ttk.Treeview(
            list_frame,
            columns=('name', 'word_count', 'create_time'),
            show='headings',
            selectmode='browse'
        )
        
        # 配置列
        columns = {
            'name': {'text': '词表名称', 'width': 120, 'anchor': 'center'},
            'word_count': {'text': '单词数量', 'width': 80, 'anchor': 'center'},
            'create_time': {'text': '创建时间', 'width': 150, 'anchor': 'center'}
        }
        
        for col, config in columns.items():
            self.wordlist_tree.heading(col, text=config['text'])
            self.wordlist_tree.column(col, width=config['width'], anchor=config['anchor'])
        

        
        # 布局Treeview和滚动条
        self.wordlist_tree.pack(side=tk.TOP, fill=tk.BOTH, expand=True)

        
        # 添加词表路径显示区域（与Treeview平级）
        self.create_path_display(list_frame)
        
        # 绑定选择事件
        self.wordlist_tree.bind('<<TreeviewSelect>>', self.on_wordlist_select)

    def create_path_display(self, parent_frame):
        """创建词表路径显示区域"""
        # 路径显示框架
        path_frame = ttk.Frame(parent_frame)
        path_frame.pack(side=tk.BOTTOM, fill=tk.X, pady=(1, 0))
        
        # 路径标签
        ttk.Label(
            path_frame,
            text="词表存储目录:",
            style='Content.TLabel',
            font=("Microsoft YaHei", 9)
        ).pack(side=tk.LEFT, padx=(0, 5))
        
        # 路径显示文本框（只读）
        self.path_text = tk.Text(
            path_frame,
            height=1,
            font=("Microsoft YaHei", 8),
            wrap='none',  # 不自动换行
            bg='#F5F5F5',
            fg='#666666',
            relief='flat',
            state='disabled'
        )
        self.path_text.pack(side=tk.LEFT, fill=tk.X, expand=True)
        


    
    def create_content_display(self):
        """创建词表内容显示区域"""
        content_frame = ttk.LabelFrame(
            self.right_frame,
            text="词表内容",
            padding=(10, 5, 10, 5),
            style='#FEFEFE.TLabelframe'
        )
        content_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 内容文本框
        self.wordlist_content_text = tk.Text(
            content_frame,
            height=15,
            width=40,
            font=("Microsoft YaHei", 10),
            wrap='word',
            bg=self.maintextframe_color,
            fg='black',
            insertbackground='black',
            padx=5,
            pady=5
        )
        
        # 滚动条
        content_scrollbar = ttk.Scrollbar(
            content_frame,
            orient='vertical',
            command=self.wordlist_content_text.yview
        )
        self.wordlist_content_text.configure(yscrollcommand=content_scrollbar.set)
        
        # 布局
        self.wordlist_content_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        content_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
    
    def create_bottom_buttons(self):
        """创建底部按钮区域（包含状态切换逻辑）"""
        self.button_frame = ttk.Frame(self.left_frame)
        self.button_frame.pack(fill=tk.X, padx=5, pady=(0, 5))
        
        # 初始只显示"新建词表"按钮
        self.new_btn = ttk.Button(
            self.button_frame,
            text="新建词表",
            command=self.start_new_wordlist,
            style='Accent.TButton'
        )
        self.new_btn.pack(side=tk.TOP, fill=tk.X, padx=2, pady=2)
        
        # 名称输入框框架
        self.name_frame = ttk.Frame(self.button_frame)
        
        self.name_label = ttk.Label(
            self.name_frame,
            text="词表名称:",
            style='Content.TLabel'
        )
        self.name_label.pack(side=tk.LEFT, padx=2)
        
        self.name_entry = ttk.Entry(
            self.name_frame,
            width=20
        )
        self.name_entry.pack(side=tk.LEFT, padx=2, expand=True, fill=tk.X)
        
        # 编辑按钮组框架
        self.edit_btn_frame = ttk.Frame(self.button_frame)
        
        self.import_btn = ttk.Button(
            self.edit_btn_frame,
            text="导入文本",
            command=self.import_text_to_wordlist,
            style='Accent.TButton'
        )
        self.import_btn.pack(side=tk.LEFT, padx=2, expand=True, fill=tk.X)
        
        self.save_btn = ttk.Button(
            self.edit_btn_frame,
            text="保存",
            command=self.save_wordlist,
            style='Accent.TButton'
        )
        self.save_btn.pack(side=tk.LEFT, padx=2, expand=True, fill=tk.X)
        
        self.cancel_btn = ttk.Button(
            self.edit_btn_frame,
            text="取消",
            command=self.cancel_edit,
            style='Accent.TButton'
        )
        self.cancel_btn.pack(side=tk.LEFT, padx=2, expand=True, fill=tk.X)
        
        # 删除按钮框架
        self.del_btn_frame = ttk.Frame(self.button_frame)
        
        self.del_btn = ttk.Button(
            self.del_btn_frame,
            text="删除词表",
            command=self.delete_selected_wordlist,
            style='Accent.TButton'
        )
        self.del_btn.pack(fill=tk.X, padx=2, pady=2)
        
        # 初始状态
        self.reset_to_initial_state()
    
    def reset_to_initial_state(self):
        """重置为初始状态（显示新建按钮，隐藏其他）"""
        self.current_edit_mode = False
        self.name_frame.pack_forget()
        self.edit_btn_frame.pack_forget()
        self.del_btn_frame.pack_forget()
        self.new_btn.pack(side=tk.LEFT, padx=2, expand=True, fill=tk.X)  # 改为LEFT布局

    
    def start_new_wordlist(self):
        """开始新建词表（隐藏新建按钮，显示编辑控件）"""
        self.current_edit_mode = True
        
        # 清空内容
        self.wordlist_content_text.delete(1.0, tk.END)
        self.name_entry.delete(0, tk.END)
        
        # 切换按钮显示
        self.new_btn.pack_forget()  # 隐藏新建按钮
        self.del_btn_frame.pack_forget()
        self.name_frame.pack(side=tk.TOP, fill=tk.X, padx=2, pady=2)
        self.edit_btn_frame.pack(side=tk.TOP, fill=tk.X, padx=2, pady=2)
        
        self.name_entry.focus()
    
    def cancel_edit(self):
        """取消编辑模式（恢复初始状态）"""
        self.reset_to_initial_state()
        self.wordlist_content_text.delete(1.0, tk.END)
    
    def on_wordlist_select(self, event):
        """当选择词表时显示删除按钮（与新建按钮并列显示）"""
        if self.current_edit_mode:
            return
        
        selected_item = self.wordlist_tree.selection()
        if not selected_item:
            return
        
        # 确保新建按钮可见
        if not self.new_btn.winfo_ismapped():
            self.new_btn.pack(side=tk.LEFT, padx=2, expand=True, fill=tk.X)
        
        # 显示删除按钮（与新建按钮并列）
        self.del_btn_frame.pack(side=tk.LEFT, padx=2, expand=True, fill=tk.X)
        
        # 隐藏编辑控件（如果存在）
        self.name_frame.pack_forget()
        self.edit_btn_frame.pack_forget()
        
        # 显示词表内容
        item = self.wordlist_tree.item(selected_item)
        wordlist_name = item['values'][0]
        wordlist_info = self.wordlists.get(wordlist_name)
        
        if wordlist_info:
            self.wordlist_content_text.delete(1.0, tk.END)
            self.wordlist_content_text.insert(tk.END, "\n".join(wordlist_info['words']))
    
    def get_wordlists_dir(self):
        """获取词表存储目录"""
        if getattr(sys, 'frozen', False):
            base_path = os.path.dirname(sys.executable)
        else:
            base_path = os.path.dirname(os.path.abspath(__file__))
        
        wordlists_dir = os.path.join(base_path, 'user_wordlists')
        os.makedirs(wordlists_dir, exist_ok=True)
        return wordlists_dir
    
    def load_wordlists(self):
        """加载所有用户词表"""
        wordlists_dir = self.get_wordlists_dir()
        self.wordlists = {}
        
        # 清空Treeview
        for item in self.wordlist_tree.get_children():
            self.wordlist_tree.delete(item)
        
        # 设置路径显示（始终显示存储目录）
        self.path_text.configure(state='normal')
        self.path_text.delete(1.0, tk.END)
        self.path_text.insert(tk.END, wordlists_dir)
        self.path_text.configure(state='disabled')
        
        # 加载词表文件
        for filename in os.listdir(wordlists_dir):
            if filename.endswith('.json'):
                filepath = os.path.join(wordlists_dir, filename)
                try:
                    with open(filepath, 'r', encoding='utf-8') as f:
                        data = json.load(f)
                        wordlist_name = data.get('name', os.path.splitext(filename)[0])
                        words = data.get('words', [])
                        create_time = data.get('create_time', '未知')
                        
                        self.wordlists[wordlist_name] = {
                            'filepath': filepath,
                            'words': words,
                            'create_time': create_time
                        }
                        
                        # 添加到Treeview
                        self.wordlist_tree.insert('', 'end', values=(
                            wordlist_name,
                            len(words),
                            create_time
                        ))
                except Exception as e:
                    print(f"加载词表 {filename} 失败: {e}")
                    
    def import_text_to_wordlist(self):
        """导入文本到当前编辑的词表"""
        wordlist_name = self.name_entry.get().strip()
        if not wordlist_name:
            messagebox.showwarning("警告", "请先输入词表名称")
            return
        
        filepath = filedialog.askopenfilename(
            title="选择文本文件",
            filetypes=[("文本文件", "*.txt"), ("所有文件", "*.*")]
        )
        
        if not filepath:
            return
        
        try:
            with open(filepath, 'r', encoding='utf-8') as f:
                text = f.read()
            
            words = self.extract_words_from_text(text)
            self.wordlist_content_text.delete(1.0, tk.END)
            self.wordlist_content_text.insert(tk.END, "\n".join(words))
            
            messagebox.showinfo("成功", f"已导入 {len(words)} 个单词")
        except Exception as e:
            messagebox.showerror("错误", f"导入失败: {str(e)}")
    
    def extract_words_from_text(self, text):
        """从文本中提取有效英文单词（排除中文和其他非字母字符）"""
        # 替换各种分隔符为空格
        text = re.sub(r'[,;，；\n\t]', ' ', text)
        
        # 使用正则表达式匹配纯英文单词
        words = []
        for word in re.findall(r'\b[a-zA-Z]+\b', text):  # 只匹配由字母组成的单词
            word = word.strip().lower()
            if word:  # 确保非空
                words.append(word)
        
        # 去重排序
        return sorted(list(set(words)))
    
    def save_wordlist(self):
        """保存当前编辑的词表"""
        wordlist_name = self.name_entry.get().strip()
        if not wordlist_name:
            messagebox.showwarning("警告", "请输入词表名称")
            return
        
        content = self.wordlist_content_text.get(1.0, tk.END).strip()
        if not content:
            messagebox.showwarning("警告", "词表内容不能为空")
            return
        
        # 提取有效单词
        words = [w.strip().lower() for w in content.split('\n') if w.strip() and w.strip().isalpha()]
        
        if not words:
            messagebox.showwarning("警告", "没有有效的单词可保存")
            return
        
        # 准备数据
        wordlist_data = {
            'name': wordlist_name,
            'words': words,
            'create_time': time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        }
        
        # 保存文件
        wordlists_dir = self.get_wordlists_dir()
        filename = f"{wordlist_name}.json"
        filepath = os.path.join(wordlists_dir, filename)
        
        try:
            with open(filepath, 'w', encoding='utf-8') as f:
                json.dump(wordlist_data, f, ensure_ascii=False, indent=2)
            
            messagebox.showinfo("成功", f"词表 '{wordlist_name}' 已保存")
            self.load_wordlists()  # 刷新列表
            self.reset_to_initial_state()  # 恢复初始状态
            # 刷新主程序的词表选择框
            if hasattr(self.parent_frame.master.master, 'wordlist_combobox'):
                wordlist_names = list(self.wordlists.keys())
                self.parent_frame.master.master.wordlist_combobox['values'] = wordlist_names       
     
        except Exception as e:
            messagebox.showerror("错误", f"保存失败: {str(e)}")
    
    def delete_selected_wordlist(self):
        """删除选中的词表"""
        selected_item = self.wordlist_tree.selection()
        if not selected_item:
            messagebox.showwarning("警告", "请先选择要删除的词表")
            return
        
        item = self.wordlist_tree.item(selected_item)
        wordlist_name = item['values'][0]
        
        if not messagebox.askyesno("确认", f"确定要删除词表 '{wordlist_name}' 吗？"):
            return
        
        wordlist_info = self.wordlists.get(wordlist_name)
        if not wordlist_info:
            messagebox.showerror("错误", "找不到选中的词表")
            return
        
        try:
            os.remove(wordlist_info['filepath'])
            messagebox.showinfo("成功", f"词表 '{wordlist_name}' 已删除")
            self.load_wordlists()  # 刷新列表
            self.wordlist_content_text.delete(1.0, tk.END)  # 清空内容
            self.reset_to_initial_state()  # 恢复初始状态
            # 刷新主程序的词表选择框
            if hasattr(self.parent_frame.master.master, 'wordlist_combobox'):
                wordlist_names = list(self.wordlists.keys())
                self.parent_frame.master.master.wordlist_combobox['values'] = wordlist_names
                # 如果删除的是当前默认词表，清空默认词表设置
                if wordlist_name == self.parent_frame.master.master.default_wordlist.get():
                    self.parent_frame.master.master.default_wordlist.set('')
                    self.parent_frame.master.master.save_default_wordlist_setting()

        except Exception as e:
            messagebox.showerror("错误", f"删除失败: {str(e)}")
    
    def get_all_wordlists(self, word=None):
        """获取所有词表数据，如果传入单词则返回包含该单词的词表列表"""
        if word is None:
            return self.wordlists
        
        word = word.lower()
        matching_wordlists = []
        
        for wordlist_name, wordlist_info in self.wordlists.items():
            if word in wordlist_info['words']:
                matching_wordlists.append(wordlist_name)
        
        return matching_wordlists

    def is_word_in_any_list(self, word):
        """检查单词是否存在于任何词表中（供外部调用）"""
        word = word.lower()
        for wordlist_info in self.wordlists.values():
            if word in wordlist_info['words']:
                return True
        return False








if __name__ == "__main__":
    app = WordCaptureTool()